﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using AutoMapper;

using Revis.VClinicNet.Core.Domain;
using Revis.VClinicNet.Core.Domain.Repository;
using Revis.VClinicNet.App.Internal.Dto;
using Revis.VClinicNet.App.Internal.Dto.Validation;
using Revis.VClinicNet.Core.Domain.Credentials;

namespace Revis.VClinicNet.App.Internal.ServiceImpl
{
    public class PatientService : IPatientService
    {
        private IPatientRepository _patientRepository = null;
        private IPatientUserRepository _patientUserRepository = null;
        private IDoctorRepository _doctorRepository = null;

        public PatientService(IPatientRepository ipr, IDoctorRepository idr, IPatientUserRepository ipur)
        {
            _patientRepository = ipr;
            _patientUserRepository = ipur;
            _doctorRepository = idr;
        }


        public long Create(PatientCreateDto patientCreateDto)
        {
            Validation.For<PatientCreateDto>().Using<PatientCreateDtoRules>().Check(patientCreateDto);

            Doctor doctor = _doctorRepository.Find(patientCreateDto.DoctorId);
            if (doctor == null) {
                throw new ClinicException("Nie znaleziono takiego lekarza");
            }

            PersonalDataDto personal = patientCreateDto.Personal;
            AddressDto address = personal.Address;

            Patient patient = _patientRepository.Find(personal.Pesel);
            if (patient != null) {
                throw new ClinicException("Pacjent o takim peselu już istnieje");
            }

            Patient newPatient = new Patient(
                new PersonalData(
                    personal.FirstName,
                    personal.Surname,
                    personal.Pesel,
                    new Address(
                        address.StreetName,
                        address.HomeNumber,
                        address.PostalCode,
                        address.City,
                        address.Municipality,
                        address.Telephone)),
                doctor);

            PatientUser newPatientUser = new PatientUser(String.Empty, newPatient);

            _patientUserRepository.Store(newPatientUser);

            return newPatient.Id;
        }

        public long Edit(PatientEditDto patientEditDto)
        {
            Validation.For<PatientEditDto>().Using<PatientEditDtoRules>().Check(patientEditDto);

            Doctor doctor = _doctorRepository.Find(patientEditDto.DoctorId);
            if (doctor == null) {
                throw new ClinicException("Nie znaleziono takiego lekarza");
            }

            Patient patient = _patientRepository.Find(patientEditDto.Id);
            if (patient == null) {
                throw new ClinicException("Nie znaleziono takiego pacjenta");
            }

            PersonalDataDto personal = patientEditDto.Personal;
            AddressDto address = personal.Address;

            patient.Change(
                new PersonalData(
                    personal.FirstName,
                    personal.Surname,
                    personal.Pesel,
                    new Address(
                        address.StreetName,
                        address.HomeNumber,
                        address.PostalCode,
                        address.City,
                        address.Municipality,
                        address.Telephone)),
                doctor);

            _patientRepository.Store(patient);

            return patient.Id;
        }

        public bool Destroy(long patientId)
        {
            throw new NotImplementedException();
        }

        public TDto Find<TDto>(long patientId)
        {
            Patient patient = _patientRepository.Find(patientId);
            TDto dto = Mapper.Map<Patient, TDto>(patient);
            return dto;
        }


        public IList<TDto> FindBy<TDto>(string field, string value)
        {
            IList<Patient> patients = _patientRepository.FindBy(field, value);
            IList<TDto> dtos = Mapper.Map<IList<Patient>, IList<TDto>>(patients);
            return dtos;
        }
    }
}
